#include <iostream>
// #include<pthread.h>
#include <vector>
#include <string>
#include <unistd.h>
#include "mutex.hpp"

using namespace std;

int tickets = 1000;
#define THREAD_NUM 4
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; // 静态分配

class threadData
{
public:
    threadData(int number, pthread_mutex_t *mutex)
    {
        threadname = "thread-" + to_string(number);
        lock = mutex;
    }

public:
    string threadname;
    pthread_mutex_t *lock;
};

void *getTicket(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    const char *name = td->threadname.c_str();
    while (true)
    {
        // 这一对花括号就是临界区
        {
            // 加锁
            // pthread_mutex_lock(td->lock);
            LockGuard LockGuard(&lock); // 临时的LockGuard对象
            // 从此完后，在{}内部，对象一创建就会自动调用构造函数，而构造函数就是加锁操作
            // {}执行完，这个临时对象就会自动被释放，而析构函数就是解锁操作
            if (tickets > 0)
            {
                usleep(1000);
                printf("who = %s, get a ticket: %d\n", name, tickets);
                --tickets;
                // 解锁
                // pthread_mutex_unlock(td->lock);
            }
            else
            {
                // 解锁
                // pthread_mutex_unlock(td->lock);
                break;
            }
        }
        usleep(13);
    }
    printf("%s ... quit\n", name);
    return nullptr;
}

int main()
{
    vector<pthread_t> tids;
    vector<threadData *> thread_datas;

    for (int i = 1; i <= THREAD_NUM; i++)
    {
        pthread_t tid;
        threadData *td = new threadData(i, &lock);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, thread_datas[i - 1]);
        tids.push_back(tid);
    }
    for (auto thread : tids)
    {
        pthread_join(thread, nullptr);
    }
    for (auto td : thread_datas)
    {
        delete td;
    }

    return 0;
}